package test;

import java.util.List;

import org.hibernate.HibernateException;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import dao.*;
import trip.*;

public class RouteDAOTest extends Assert {
	
	private CompanyDAO cD = Factory.getInstance().getCompanyDAO();
	private RouteDAO rD = Factory.getInstance().getRouteDAO();
	private TripDAO tD = Factory.getInstance().getTripDAO();
	private StopDAO sD = Factory.getInstance().getStopDAO();
	private Route_stopsDAO rsD = Factory.getInstance().getRoute_stopsDAO();
	
	@DataProvider
	public Object[][] routeData() {
		return new Object[][] {
				{1, "x", true, true},
				{2, "x", null, false},
				{1, "x", false, true},
				{50, "x", true, true},
				{50, "x", false, true},
				{null, "x", false, false},
				{1, null, false, false},
				{null, null, false, false},
				{null, null, null, false},
				{null, "x", null, false},
				{1, null, null, false}
		};
	}
	
	@Test(dataProvider="routeData")
	public void dataTest(Integer number, String name, Boolean active, boolean expected) {
		try {
			List<Route> routes = rD.getAll();
			assertNotNull(routes);
			Integer count = routes.size();
			assertNotNull(count);
			Route route = new Route(1, number, name, active);
			rD.create(route);
			Route tmpRoute = rD.getById(route.getId());
			assertNotNull(tmpRoute);
			assertEquals(tmpRoute.getId(), route.getId());
			assertEquals(tmpRoute.getNumber(), route.getNumber());
			assertEquals(tmpRoute.getName(), route.getName());
			assertEquals(tmpRoute.getActive(), route.getActive());
			int numEquals = 0;
			if (active) {
				routes = rD.getAll();
				assertNotNull(routes);
				for(Route rt : routes) {
					if (rt.getNumber() == route.getNumber() && rt.getId() != route.getId()) {
						assertFalse(rt.getActive());
						numEquals++;
					}
				}
			}
			route.setName(route.getName() + "new");
			rD.update(route);
			tmpRoute = rD.getById(route.getId());
			assertNotNull(tmpRoute);
			assertEquals(tmpRoute.getId(), route.getId());
			assertEquals(tmpRoute.getNumber(), route.getNumber());
			assertEquals(tmpRoute.getName(), route.getName());
			assertEquals(tmpRoute.getActive(), route.getActive());
			rD.delete(tmpRoute);
			if (active) {
				routes = rD.getAll();
				assertNotNull(routes);
				Route maxN = null;
				for(Route rt : routes) {
					if (rt.getNumber() == number)
						if (maxN == null)
							maxN = rt;
						else
							if(maxN.getId() < rt.getId())
								maxN = rt;
				}
				if (maxN != null)
					assertTrue(maxN.getActive());
				else
					assertTrue(numEquals == 0);
			}	
			tmpRoute = rD.getById(route.getId());
			assertNull(tmpRoute);
			assertEquals(cD.getAll().size(), count.intValue());
			assertTrue(expected);
		} catch (HibernateException ex) {
			assertFalse(expected);
		}
	}
	
		
	@Test
	public void getByStopsTest() {
		List<Route> routes = rD.getAll();
		assertNotNull(routes);
		List<Route_stops> rss =rsD.getAll();
		assertNotNull(rss);
		List<Stop> stops = sD.getAll();
		assertNotNull(stops);
		for(Stop st1 : stops) {
			for(Stop st2 : stops) {
				List<Route> rByS = rD.getByStops(st1, st2);
				assertNotNull(rByS);
				if (rByS.size() != 0 ) {
					for (Route route : rByS) {
						Integer num1 = null, num2 = null;
						for(Route_stops rs : rss) {
							if (rs.getRoute().equals(route) && rs.getStop().equals(st1))
								num1 = rs.getStopNumber();
							if (rs.getRoute().equals(route) && rs.getStop().equals(st2))
								num2 = rs.getStopNumber();
						}
						assertTrue(num1 != null && num2 != null);
						assertTrue(num1 < num2);
					}
				}
				else {
					for (Route route : routes) {
						Integer num1 = null, num2 = null;
						for(Route_stops rs : rss) {
							if (rs.getRoute().equals(route) && rs.getStop().equals(st1) &&
								rs.getRoute().getActive())
								num1 = rs.getStopNumber();
							if (rs.getRoute().equals(route) && rs.getStop().equals(st2) &&
									rs.getRoute().getActive())
								num2 = rs.getStopNumber();
						}
						if (num1 != null && num2 !=null)
							assertTrue(num1 >= num2);
					}
				}
			}
		}
	}
	
	@Test
	public void getByRouteTest() {
		List<Company> comps = cD.getAll();
		assertNotNull(comps);
		List<Route> routes = rD.getAll();
		assertNotNull(routes);
		List<Trip> trips = tD.getAll();
		assertNotNull(trips);
		for(Company comp : comps) {
			List<Route> rByC = rD.getByCompany(comp);
			assertNotNull(rByC);
			if (rByC.size() != 0) {
				for(Route route : rByC) {
					boolean found = false;
					for(Trip trip : trips) {
						if (trip.getCompany().equals(comp) && trip.getRoute().equals(route)) {
							found = true;
							break;
						}
					}
					assertTrue(found);
				}
			} 
			else {
				for(Route route : routes) {
					boolean found = false;
					for(Trip trip : trips) {
						if (trip.getCompany().equals(comp) && trip.getRoute().equals(route)) {
							found = true;
							break;
						}
					}
					assertFalse(found);
				}
			}
		}
	}
}
